package com.sudo.service.admin.service;

import com.sudo.common.component.ExtraProperties;
import com.sudo.common.component.RedisKeys;
import com.sudo.common.component.StringRedisUtil;
import com.sudo.common.constant.UserConstant;
import com.sudo.common.service.BaseService;
import com.sudo.common.utils.LocalDateTimeUtil;
import com.sudo.dao.admin.entity.SysUserRole;
import com.sudo.dao.admin.mapper.SysRoleMapperCustom;
import com.sudo.dao.admin.model.vo.SysMemCpuVO;
import com.sudo.dao.admin.model.vo.SysMenuButtonVO;
import com.sudo.dao.admin.model.vo.SysRoleButtonVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.File;
import java.util.*;

/**
 * @author 为道日损 2020-04-25 23:45
 * webSite：https://www.sudo.ren
 */
@Service
public class AdminBaseService extends BaseService {

    public final static String cpuCode = "cpu.mhz";
    public final static String memCode = "mem.total";
    @Resource
    public StringRedisUtil stringRedisUtil;
    @Resource
    private ExtraProperties extraProperties;

    @Resource
    public RedisKeys redisKeys;

    // 新文件名
    public String getNewFileName(String module, String oldFileName, String sessionUser) {
        //文件重命名 username_模块_日期_时间_微秒.png/jpg
        String[] fileNameArr = oldFileName.split("\\.");
        //文件后缀名
        String suffix = fileNameArr[fileNameArr.length - 1];
        //文件名重组
        String nowTime = LocalDateTimeUtil.convertNowTime2Str(LocalDateTimeUtil.yyyyMMdd_HHmmss_SSS);
        return sessionUser + "_" + module + "_" + nowTime + "." + suffix;
    }

    // 相对地址文件 (相对这个目录而言 extraProperties.getFileSpace())
    public String getRelativePositionFile(String module,String fileName,String sessionUser){
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append(module);
        stringBuffer.append(File.separator);
        stringBuffer.append(sessionUser);
        stringBuffer.append(File.separator);
        stringBuffer.append(fileName);
        return  stringBuffer.toString();
    }

    // 物理位置文件
    public String getPhysicalPositionFile(String relativePositionFile){
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append(extraProperties.getFileSpace());
        stringBuffer.append(File.separator);
        stringBuffer.append(relativePositionFile);
        return  stringBuffer.toString();
    }

    // 逻辑位置文件（访问位置）
    public String getLogicalPosition(String relativePositionFile){
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append(resourcePath);
        stringBuffer.append(File.separator);
        stringBuffer.append(relativePositionFile);
        return  stringBuffer.toString();
    }

    protected boolean hasStrInListStr(String str,String listStr) {
        String[] strArr = StringUtils.strip(listStr, "[]").split(",");
        List<String> strList = Arrays.asList(strArr);
        return strList.contains(str);
    }

    protected void setRedisMenuButtonToRedis(String menuCode ,String buttonCode) {
        stringRedisUtil.sAdd(redisKeys.redisMenuButton(menuCode), buttonCode);
    }

    protected void setRedisMenuButtonToRedis(List<SysMenuButtonVO> sysMenuButtonVOList) {
        for (SysMenuButtonVO t:sysMenuButtonVOList){
            stringRedisUtil.sAdd(redisKeys.redisMenuButton(t.getMenuCode()), t.getButtonCode());
        }
    }

    protected void delRedisMenuButtonFromRedis(String menuCode ,String buttonCode) {
        String key = redisKeys.redisMenuButton(menuCode);
        if (null == buttonCode) {
            stringRedisUtil.delete(key);
        }else {
            stringRedisUtil.sRemove(key, buttonCode);
        }
    }

    protected void setRedisRolePermissionToRedis(String roleCode, String menuCode, String buttonCode) {
        stringRedisUtil.sAdd(redisKeys.redisRolePermission(roleCode,menuCode), buttonCode);
    }

    protected void setRedisRolePermissionToRedis(List<SysRoleButtonVO> sysRoleButtonVOList) {
        for (SysRoleButtonVO t:sysRoleButtonVOList){
            String key = redisKeys.redisRolePermission(t.getRoleCode(), t.getMenuCode());
            if (!stringRedisUtil.hasKey(key)) {
                stringRedisUtil.sAdd(key, UserConstant.NONE);
            }else{
                stringRedisUtil.sAdd(key, t.getButtonCode());
            }
        }
    }

    protected void delRedisRolePermissionFromRedis(String roleCode, String menuCode,String buttonCode) {
        String key = redisKeys.redisRolePermission(roleCode,menuCode);
        if (null == buttonCode) {
            stringRedisUtil.delete(key);
        }else {
            stringRedisUtil.sRemove(key, buttonCode);
        }
    }

    protected void delRedisRolePermissionFromRedis(String roleCode) {
        String key = redisKeys.redisRolePermission(roleCode, "*");
        stringRedisUtil.delete(stringRedisUtil.keys(key));
    }

    protected void setRedisRoleUserToRedis(String roleCode, String username) {
        stringRedisUtil.sAdd(redisKeys.redisRoleUser(roleCode), username);
    }

    protected void updateRedisRoleForUser(String username, String oldRoleCode, String newRoleCode) {
        stringRedisUtil.sRemove(redisKeys.redisRoleUser(oldRoleCode), username);
        stringRedisUtil.sAdd(redisKeys.redisRoleUser(newRoleCode), username);
    }

    protected void delRedisRoleUserFromRedis(String roleCode, String username) {
        String key = redisKeys.redisRoleUser(roleCode);
        if (null == username) {
            stringRedisUtil.delete(key);
        } else {
            stringRedisUtil.sRemove(key, username);
        }
    }

    protected void delRedisUserTokenFromRedis(String username) {
        stringRedisUtil.delete(redisKeys.redisUserToken(username));
    }

    /**
     * 通过username从redis中获取roleCode
     * @param username 用户名
     * @return string
     */
    protected String getRoleCodeFromRedisByUsername(String username) {
        if (null == username) {
            return null;
        }
        Set<String> keys = stringRedisUtil.keys(redisKeys.redisRoleUser("*"));
        String roleCode = null;
        for (String key : keys) {
            boolean flag = stringRedisUtil.sIsMember(key,username);
            if (flag){
                roleCode = key.replace(RedisKeys.REDIS_ROLE_USER+":","");
                break;
            }
        }
        return roleCode;
    }


    /**
     * 项目启动加载所有角色对应菜单的按钮权限(可用角色 可用菜单 可用按钮)
     */
    @Resource
    private SysRoleMapperCustom sysRoleMapperCustom;
    @Transactional(propagation = Propagation.SUPPORTS, rollbackFor = Exception.class)
    public void onLoadAllRoleMenuButtonAuth(String roleCode,String menuCode) {
        //清空权限缓存
        if (null == roleCode) {
            stringRedisUtil.delete(stringRedisUtil.keys(RedisKeys.REDIS_ROLE_PERMISSION + ":*"));
        } else if (null != menuCode) {
            stringRedisUtil.delete(stringRedisUtil.keys(redisKeys.redisRolePermission(roleCode, menuCode)));
        } else {
            stringRedisUtil.delete(stringRedisUtil.keys(redisKeys.redisRolePermission(roleCode, "*")));
        }

        List<SysRoleButtonVO> sysRoleButtonVOList = sysRoleMapperCustom.getRoleMenuButtonAuth(roleCode,menuCode);
        Iterator<SysRoleButtonVO> iterator = sysRoleButtonVOList.iterator();

        while (iterator.hasNext()) {
            SysRoleButtonVO sysRoleButtonVO = iterator.next();
            String key = redisKeys.redisRolePermission(sysRoleButtonVO.getRoleCode(), sysRoleButtonVO.getMenuCode());
            if (!stringRedisUtil.hasKey(key)) {
                stringRedisUtil.sAdd(key, "none");
            }
            if (StringUtils.isNotBlank(sysRoleButtonVO.getButtonCode())) {
                stringRedisUtil.sAdd(key, sysRoleButtonVO.getButtonCode());
            }
        }
    }


    /**
     * 加载所有可用菜单的可用按钮
     */
    @Transactional(propagation = Propagation.SUPPORTS, rollbackFor = Exception.class)
    public void onLoadMenuButtonToRedis(String menuCode) {
        //清空菜单按钮缓存
        if (null == menuCode) {
            stringRedisUtil.delete(stringRedisUtil.keys(redisKeys.redisMenuButton("*")));
        } else {
            stringRedisUtil.delete(stringRedisUtil.keys(redisKeys.redisMenuButton(menuCode)));
        }
        List<SysMenuButtonVO> sysMenuButtonVOList = sysRoleMapperCustom.getMenuButtonByOn(menuCode);
        Iterator<SysMenuButtonVO> iterator = sysMenuButtonVOList.iterator();
        while (iterator.hasNext()) {
            SysMenuButtonVO sysMenuButtonVO = iterator.next();
            String key = redisKeys.redisMenuButton(sysMenuButtonVO.getMenuCode());
            stringRedisUtil.sAdd(key, sysMenuButtonVO.getButtonCode());
        }
    }

    /**
     * 加载可用角色和可用用户
     */
    @Transactional(propagation = Propagation.SUPPORTS, rollbackFor = Exception.class)
    public void onLoadSysRoleUserToRedis(String roleCode) {
        //清空角色用户缓存
        if (null == roleCode) {
            stringRedisUtil.delete(stringRedisUtil.keys(redisKeys.redisRoleUser("*")));
        } else {
            stringRedisUtil.delete(stringRedisUtil.keys(redisKeys.redisRoleUser(roleCode)));
        }

        List<SysUserRole> sysUserRoleList = sysRoleMapperCustom.getSysRoleUserCodeByOn(roleCode);
        Iterator<SysUserRole> iterator = sysUserRoleList.iterator();
        while (iterator.hasNext()) {
            SysUserRole sysUserRole = iterator.next();
            stringRedisUtil.sAdd(redisKeys.redisRoleUser(sysUserRole.getRoleCode()), sysUserRole.getUsername());
        }
    }

    public void setSysCpuMemInfoByRealTime(String key,String value) {
        long len = stringRedisUtil.getListSize(key);
        if (len>=20){
            stringRedisUtil.lRightPop(key);
            setSysCpuMemInfoByRealTime(key,value);
        }else {
            stringRedisUtil.lLeftPush(key,value);
        }
    }



    public static SysMemCpuVO map2MemCpu(Map<String ,Object> objectMap) {
        SysMemCpuVO sysMemCpuVO = new SysMemCpuVO();
        /*sysMemLog.setMemTotal(objectMap.get("memTotal").toString());
        sysMemLog.setMemUsed(objectMap.get("memUsed").toString());
        sysMemLog.setMemFree(objectMap.get("memFree").toString());
        sysMemLog.setMemFreePercent(objectMap.get("memFreePercent").toString());*/
        sysMemCpuVO.setC(Float.parseFloat(objectMap.get("cpuTotal").toString()));
        sysMemCpuVO.setM(Float.parseFloat(objectMap.get("memUsedPercent").toString()));
        sysMemCpuVO.setT(Long.parseLong(objectMap.get("now").toString()));
        return sysMemCpuVO;
    }
}
